/********************************************************************
	file name:	hy_atom.h
	created:	2012/03/30 19:23
	author:		supercaco@sina.com
	purpose:	atomic operation
*********************************************************************/
#ifndef _HY_ATOM_H_
#define _HY_ATOM_H_

namespace hy_os
{

/*******************************************************************/
/*						atom hand function   					   */
/*******************************************************************/
/*
 * function atom_compare_and_swap(lock, old, new):
 * {
 *		old_value = lock;
 *		if (lock == old)
 *			lock = new;
 *		return old_value;
 * }
 *
 * function atom_fetch_add(lock, value):
 * {
 *		old_value = lock;
 *		lock += value;
 *		return old_value;
 * }
 * function atom_inc(lock)
 * {
 *		lock += 1;
 *		return lock;
 * }
 * function atom_dec(lock)
 * {
 *		lock -= 1;
 *		return lock;
 * }
 * function atom_set(lock, value)
 * {
 *		old_value = lock;
 *		lock = value;
 *		return old_value;
 * }
 * function atom_or_fetch(lock, value)
 * {
 *		newvalue = lock | value;
 *		lock = newvalue;
 *		return newvalue;
 * }
 * function atom_and_fetch(lock, value)
 * {
 *		newvalue = lock & value;
 *		lock = newvalue;
 *		return newvalue;
 * }
 * */

#ifdef _WIN32

#define atom_compare_and_swap(lock, old, new) InterlockedCompareExchange(lock, new, old)
#define atom_fetch_add	InterlockedExchangeAdd
#define atom_inc		InterlockedIncrement
#define atom_dec		InterlockedDecrement
#define atom_set		InterlockedExchange

inline long atom_or_fetch (volatile long *lock, long value)
{
	long old, newvalue;
	do {
		old = *lock;
		newvalue = old | value;
	} while (InterlockedCompareExchange(lock, newvalue, old) != old);

	return newvalue;
}

inline long atom_and_fetch (volatile long *lock, long value)
{
	long old, newvalue;
	do {
		old = *lock;
		newvalue = old & value;
	} while (InterlockedCompareExchange(lock, newvalue, old) != old);

	return newvalue;
}

#else
//gcc 4.1.2 spport built-in functions
#define atom_compare_and_swap	__sync_val_compare_and_swap
#define atom_fetch_add			__sync_fetch_and_add
#define atom_inc(lock)			__sync_add_and_fetch(lock, 1)
#define atom_dec(lock)			__sync_add_and_fetch(lock, -1)
#define atom_set				__sync_lock_test_and_set
#define atom_or_fetch			__sync_or_and_fetch
#define atom_and_fetch			__sync_and_and_fetch

#endif

}; //namspace hy
#endif  //_HY_ATOM_H_
